﻿namespace TransitDataParser
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// Parses a CSV line and returns the columns.
    /// </summary>
    internal class CSVLineParser : ICSVLineParser
    {
        /// <summary>
        /// Parses given CSV line
        /// </summary>
        /// <param name="line">Line that contains comma sepearated values</param>
        /// <returns>Array of elements after parsing</returns>
        public string[] ParseLine2(string line)
        {
            List<string> strings = new List<string>();
            StringBuilder builder = new StringBuilder();

            bool inQuotedString = false;
            char lastChar = default(char);

            foreach (char c in line)
            {
                if (c == '"')
                {
                    if (lastChar == '"')
                    {
                        builder.Append(c);
                    }
                    else
                    {
                        inQuotedString = !inQuotedString;
                    }
                }
                else if (c == ',')
                {
                    if (inQuotedString)
                    {
                        builder.Append(c);
                    }
                    else
                    {
                        strings.Add(builder.ToString());
                        builder.Clear();
                    }
                }
                else
                {
                    builder.Append(c);
                }

                lastChar = c;
            }

            if (builder.Length > 0)
            {
                strings.Add(builder.ToString());
            }
            else if (lastChar == ',')
            {
                strings.Add(String.Empty);
            }

            return strings.ToArray();
        }

        /// <summary>
        /// Parses given CSV line
        /// </summary>
        /// <param name="line">Line that contains comma sepearated values</param>
        /// <returns>Array of elements after parsing</returns>
        public string[] ParseLine(string line)
        {
            List<string> strings = new List<string>();
            StringBuilder builder = new StringBuilder();

            int state = 1;
            // char lastChar = default(char);
            foreach (char c in line)
            {
                switch (state)
                {
                    case 1:
                        if (c == ',')
                        {
                            strings.Add(builder.ToString());
                            builder.Clear();
                        }
                        else if (c == '"')
                        {
                            state = 2;
                        }
                        else
                        {
                            builder.Append(c);
                            state = 4;
                        }

                        break;

                    case 2:
                        if (c == '"')
                        {
                            state = 3;
                        }
                        else
                        {
                            builder.Append(c);
                        }

                        break;

                    case 3:
                        if (c == '"')
                        {
                            state = 2;
                            builder.Append(c);
                        }
                        else if (c == ',')
                        {
                            state = 1;
                            strings.Add(builder.ToString());
                            builder.Clear();
                        }
                        else
                        {
                            builder.Append(c);
                        }

                        break;

                    case 4:
                        if (c == ',')
                        {
                            state = 1;
                            strings.Add(builder.ToString());
                            builder.Clear();
                        }
                        else
                        {
                            builder.Append(c);
                        }

                        break;
                }

                // lastChar = c;
            }

            strings.Add(builder.ToString());

            return strings.ToArray();
        }
    }
}
